package com.shell.governor.authentication.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.base.utils.SystemUtil;
import com.shell.bee.entity.auth.AuthOrgan;
import com.shell.bee.entity.auth.AuthResource;
import com.shell.bee.entity.auth.AuthUser;
import com.shell.constant.ind.PubConstants;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.governor.audit.online.service.PubOnlineHistService;
import com.shell.governor.audit.online.service.PubOnlineService;
import com.shell.governor.audit.po.PubOnline;
import com.shell.governor.authentication.service.AuthService;
import com.shell.governor.authorization.po.PubResource;
import com.shell.governor.authorization.service.PubResourceService;
import com.shell.governor.authorization.service.PubRoleService;
import com.shell.governor.modules.po.PubApplication;
import com.shell.governor.modules.service.PubApplicationService;
import com.shell.governor.organization.service.PubOrganService;
import com.shell.governor.organization.vo.PubOrganVo;
import com.shell.governor.user.po.PubUser;
import com.shell.governor.user.service.PubUserService;
import com.shell.governor.user.vo.PubUserVo;
import com.shell.governor.user.vo.UserQueryVo;
import com.shell.governor.util.TransformHelper;

@Service
public class AuthServiceImpl implements AuthService {

	protected final Log logger = LogFactory.getLog(getClass());

	@Autowired
	private PubUserService pubUserService;
	@Autowired
	private PubRoleService pubRoleService;
	@Autowired
	private PubResourceService pubResourceService;
	@Autowired
	private PubOnlineHistService onlineHistService;
	@Autowired
	private PubOnlineService onlineService;
	@Autowired
	private PubOrganService pubOrganService;
	@Autowired
	private PubApplicationService pubApplicationService;

	public AuthUser getUserByPrincipal(String principal) {
		PubUserVo user = this.pubUserService.findUserByLoginName(principal);
		if (user == null) {
			return null;
		}
		AuthUser authUser = new AuthUser();
		authUser.setUserId(user.getUserId());
		authUser.setLoginName(user.getLoginName());
		authUser.setUserName(user.getUserName());
		authUser.setPassword(user.getPassword());
		authUser.setUserState(user.getUserState());

		AuthOrgan organ = new AuthOrgan();
		organ.setOrganId(user.getEntId());

		authUser.setEnt(organ);

		return authUser;
	}

	public void afterLogged(String userId, String entId, String appCode) {
		PubUser user = (PubUser) this.pubUserService.selectByKey(userId);

		String token = SystemUtil.getUUID();
		String loginAddr = CommonDataUtil.getCurUserIp();
		this.onlineService.saveOnlineRecord(token, user.getLoginName(), loginAddr);
	}

	public AuthUser getLoggedUser(String userId, String entId, String appCode, String terminalCode) {
		PubUser user = (PubUser) this.pubUserService.selectByKey(userId);

		AuthUser authUser = new AuthUser();
		authUser.setUserId(user.getUserId());
		authUser.setLoginName(user.getLoginName());
		authUser.setUserName(user.getUserName());
		authUser.setPassword(user.getPassword());

		setAuthInfo(authUser, entId, appCode, terminalCode);

		return authUser;
	}

	private void setAuthInfo(AuthUser authUser, String entId, String appCode, String terminalCode) {
		if (StringUtil.emptyAndNull(appCode)) {
			appCode = "GOVERNOR";
		}
		authUser.setExtension(new HashMap());
		List<PubOrganVo> ents = this.pubOrganService.queryUserEnt(authUser.getUserId());

		PubOrganVo ent = null;
		if ((ents != null) && (ents.size() > 0)) {
			if (StringUtil.notEmpty(entId)) {
				for (PubOrganVo ov : ents) {
					if (ov.getOrganId().equals(entId)) {
						ent = ov;
					}
				}
			} else {
				ent = (PubOrganVo) ents.get(0);
			}
		}
		Object roles = null;
		if (ent == null) {
			authUser.getExtension().put("isHasAppPermission", Boolean.valueOf(true));
			authUser.setMenuTree(new ArrayList());
		} else {
			roles = this.pubRoleService.selectUserRole(authUser.getUserId(), ent.getOrganId());
		}
		if (null != roles) {
			authUser.setEnt(TransformHelper.transformOrgan(ent));
			authUser.getExtension().put("ents", ents);

			authUser.setRoles(TransformHelper.transformRoles((List) roles));
			try {
				PubApplication application = new PubApplication();
				application.setAppCode(appCode);
				List<PubApplication> list = this.pubApplicationService.getApplication(application);
				List<PubResource> userRess = null;
				if (StringUtil.notEmpty(terminalCode)) {
					terminalCode = PubConstants.TerminalCode.TRML_PC;
				}
				List<PubResource> ress = this.pubResourceService.selectAllResourceTree4User(authUser.getUserId(),
						ent.getOrganId(), terminalCode, ((PubApplication) list.get(0)).getAppId());
				List<PubApplication> applications = this.pubApplicationService
						.selectCurUserApplication(authUser.getUserId(), ent.getOrganId(), "");
				authUser.getExtension().put("authApps", applications);
				userRess = genPubResouceByApplication(applications, ress, appCode);
				if (StringUtil.emptyAndNull(ent.getOrganCode())) {
					authUser.getExtension().put("isHasAppPermission", Boolean.valueOf(true));
				} else {
					authUser.getExtension().put("isHasAppPermission",
							Boolean.valueOf(hasAppPermission(applications, appCode)));
				}
				authUser.setMenuTree(genAuthResourceTree(userRess));
			} catch (Exception e) {
				e.printStackTrace();
				this.logger.error("����������������������", e);
			}
		}
	}

	private boolean hasAppPermission(List<PubApplication> applications, String appCode) {
		for (PubApplication application : applications) {
			if (application.getAppCode().equals(appCode)) {
				return true;
			}
		}
		return false;
	}

	private List<PubResource> genPubResouceByApplication(List<PubApplication> applications, List<PubResource> ress,
			String appCode) {
		List<PubResource> pubResources = new ArrayList();
		for (PubApplication application : applications) {
			if (!application.getAppCode().equals(appCode)) {
				PubResource resource = new PubResource();
				String openMode = application.getOpenMode();
				if (StringUtil.emptyAndNull(openMode)) {
					openMode = "target_blank";
				}
				resource.setOpenMode(openMode);
				resource.setAppId(application.getAppId());
				resource.setResName(application.getAppAlias());
				resource.setResValue(application.getAppUrl());
				resource.setResType("res_type_0,res_type_1");
				resource.setResState(application.getAppState());
				resource.setResCode(application.getAppCode());
				resource.setTrmlCode(PubConstants.TerminalCode.TRML_PC);
				resource.setResLevel(Integer.valueOf(0));
				resource.setChecked(true);
				pubResources.add(resource);
			} else {
				pubResources.addAll(ress);
			}
		}
		return pubResources;
	}

	public void afterLogouted(AuthUser user) {
		if (user != null) {
			this.logger.info("user��" + user);
			PubOnline online = new PubOnline();
			String token = "";
			online.setOnlineId(token);
			online.setLoginName(user.getLoginName());
			this.onlineHistService.saveOnlineHistRecord(online);
		}
	}

	public void afterSessionExpired(AuthUser user) {
		if (user != null) {
			this.logger.info("user��" + user);
			PubOnline online = new PubOnline();
			String token = "";
			online.setOnlineId(token);
			online.setLoginName(user.getLoginName());
			this.onlineHistService.saveOnlineHistRecord(online);
		}
	}

	private List<AuthResource> genAuthResourceTree(List<PubResource> ress) {
		if ((ress == null) || (ress.size() == 0)) {
			return null;
		}
		List<AuthResource> aress = new ArrayList();
		for (PubResource res : ress) {
			AuthResource ares = new AuthResource();
			BeanUtils.copyProperties(res, ares);
			if ((res.getChildren() != null) && (res.getChildren().size() > 0)) {
				ares.setChildren(genAuthResourceTree(res.getChildren()));
			}
			aress.add(ares);
		}
		return aress;
	}

	public void changeEnt(String entId) {
	}

	public boolean isMultipleUser(String userName) {
		UserQueryVo userVo = new UserQueryVo();
		userVo.setLoginName(userName);
		String[] notStates = { "F", "D", "U" };
		userVo.setNotStates(notStates);
		List<PubUserVo> fusers = this.pubUserService.queryUser(userVo);
		return (fusers != null) && (fusers.size() > 1);
	}
}
